home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / daemons / init / sysvinit.000 / sysvinit / sysvinit-2.64 / init.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-06-28  |  47.9 KB  |  2,023 lines

  1. /*
  2.  * Init        A System-V Init Clone.
  3.  *
  4.  * Usage:    /sbin/init
  5.  *             init [0123456SsQqAaBbCc]
  6.  *          telinit [0123456SsQqAaBbCc]
  7.  *
  8.  * Version:    @(#)init.c  2.64  28-Jun-1996  MvS
  9.  *
  10.  *        This file is part of the sysvinit suite,
  11.  *        Copyright 1991-1996 Miquel van Smoorenburg.
  12.  *
  13.  *        This program is free software; you can redistribute it and/or
  14.  *        modify it under the terms of the GNU General Public License
  15.  *        as published by the Free Software Foundation; either version
  16.  *        2 of the License, or (at your option) any later version.
  17.  */
  18.  
  19. /* Standard configuration */
  20. #define SYSLOG       1            /* Use syslog for messages */
  21. #define CHANGE_WAIT 0            /* Do not change runlevel while
  22.                        waiting for a process to exit */
  23. #define NEWINIT     1            /* Enable use of /dev/initctl */
  24.  
  25. /* Debug and test modes */
  26. #define DEBUG       0            /* Debug code off */
  27. #define INITDEBUG  0            /* Fork at startup so we can debug init. */
  28. #define CLEAN_UTMP 1            /* Do garbage collect in utmp*/
  29. #undef  ROOTFS       "/dev/hda2"        /* Root fs to use */
  30.  
  31. /* Some constants */
  32. #define INITPID       1            /* pid of first process */
  33. #define PIPE_FD    10            /* Fileno of initfifo. */
  34.  
  35. /* Failsafe configuration */
  36. #define MAXSPAWN   10            /* Max times respawned in.. */
  37. #define TESTTIME   120            /* this much seconds */
  38. #define SLEEPTIME  300            /* Disable time */
  39.  
  40. /* Default path inherited by every child if it's not set. */
  41. #define PATH_DFL   "PATH=/bin:/sbin:/usr/bin:/usr/sbin"
  42.  
  43. #include <sys/types.h>
  44. #include <sys/stat.h>
  45. #include <sys/ioctl.h>
  46. #include <sys/wait.h>
  47. #include <sys/kd.h>
  48. #include <stdlib.h>
  49. #include <unistd.h>
  50. #include <errno.h>
  51. #include <stdio.h>
  52. #include <time.h>
  53. #include <fcntl.h>
  54. #include <string.h>
  55. #include <signal.h>
  56. #include <termios.h>
  57. #include <utmp.h>
  58. #include <ctype.h>
  59. #include <stdarg.h>
  60. #if SYSLOG
  61. #  include <sys/syslog.h>
  62. #endif
  63. #if NEWINIT
  64. #  include <sys/time.h>
  65. #  include "initreq.h"
  66. #endif
  67. #include "paths.h"
  68.  
  69. #ifndef NO_PROCESS
  70. #  define NO_PROCESS 0
  71. #endif
  72. #ifndef SIGPWR
  73. #  define SIGPWR SIGUSR1
  74. #endif
  75.  
  76. /* Set a signal handler. */
  77. #define SETSIG(sa, sig, fun)    sa.sa_handler = fun; \
  78.                 sa.sa_flags = SA_RESTART; \
  79.                 sigaction(sig, &sa, NULL);
  80.  
  81. /* Version information */
  82. char *Version = "@(#) init 2.64 28-Jun-1996 MvS";
  83. char *bootmsg = "version 2.64 booting";
  84. #define E_VERSION "INIT_VERSION=sysvinit-2.64"
  85.  
  86. /* Information about a process in the in-core inittab */
  87. typedef struct _child_ {
  88.   int flags;            /* Status of this entry */
  89.   int exstat;            /* Exit status of process */
  90.   int pid;            /* Pid of this process */
  91.   time_t tm;            /* When respawned last */
  92.   int count;            /* Times respawned in the last 2 minutes */
  93.   char id[8];            /* Inittab id (must be unique) */
  94.   char rlevel[12];        /* run levels */
  95.   int action;            /* what to do (see list below) */
  96.   char process[128];        /* The command line */
  97.   struct _child_ *new;        /* New entry (after inittab re-read) */
  98.   struct _child_ *next;        /* For the linked list */
  99. } CHILD;
  100.  
  101. CHILD *family = NULL;        /* The linked list of all entries */
  102. CHILD *newFamily = NULL;    /* The list after inittab re-read */
  103.  
  104. CHILD ch_emerg = {        /* Emergency shell */
  105.   0, 0, 0, 0, 0,
  106.   "~~",
  107.   "S",
  108.   3,
  109.   "/sbin/sulogin",
  110.   NULL,
  111.   NULL
  112. };
  113.  
  114. char runlevel = 'S';        /* The current run level */
  115. char thislevel = 'S';        /* The current runlevel */
  116. char prevlevel = 'N';        /* Previous runlevel */
  117. int dflLevel = 0;        /* Default runlevel */
  118. int got_cont = 0;        /* Set if we received the SIGCONT signal */
  119. int emerg_shell = 0;        /* Start emergency shell? */
  120. sigset_t got_signals;        /* Set if we received a signal. */
  121. int wroteReboot    = 1;        /* Set when we wrote the reboot record */
  122. int sltime = 5;            /* Sleep time between TERM and KILL */
  123. char *argv0;            /* First arguments; show up in ps listing */
  124. int maxproclen;            /* Maximal length of argv[0] */
  125. struct utmp utproto;        /* Only used for sizeof(utproto.ut_id) */
  126. char *console_dev = CONSOLE;    /* Console device. */
  127. int wroteiosave = 0;        /* Did we write ioctl.save yet? */
  128.  
  129. /* Prototypes. */
  130. void Wtmp(char *user, char *id, int pid, int type, char *line);
  131. void WtmpOnly(char *user, char *id, int pid, int type, char *line);
  132. void Log(int loglevel, char *fmt, ...);
  133. void SetTerm(int how);
  134. void print(char *fmt);
  135.  
  136. /* Actions to be taken by init */
  137. #define RESPAWN            1
  138. #define WAIT            2
  139. #define ONCE            3
  140. #define    BOOT            4
  141. #define BOOTWAIT        5
  142. #define POWERFAIL        6
  143. #define POWERWAIT        7
  144. #define POWEROKWAIT        8
  145. #define CTRLALTDEL        9
  146. #define OFF               10
  147. #define    ONDEMAND           11
  148. #define    INITDEFAULT           12
  149. #define SYSINIT               13
  150. #define POWERFAILNOW           14
  151. #define KBREQUEST               15
  152.  
  153. /* Macro to see if this is a special action */
  154. #define ISPOWER(i) ((i) == POWERWAIT || (i) == POWERFAIL || \
  155.             (i) == POWEROKWAIT || (i) == POWERFAILNOW || \
  156.             (i) == CTRLALTDEL)
  157.  
  158. /* Values for the 'flags' field */
  159. #define RUNNING            2    /* Process is still running */
  160. #define KILLME            4    /* Kill this process */
  161. #define DEMAND            8    /* "runlevels" a b c */
  162. #define FAILING            16    /* process respawns rapidly */
  163. #define WAITING            32    /* We're waiting for this process */
  164. #define ZOMBIE            64    /* This process is already dead */
  165. #define XECUTED        128    /* Set if spawned once or more times */
  166.  
  167. /* Log levels. */
  168. #define L_CO    1        /* Log on the console. */
  169. #define L_SY    2        /* Log with syslog() */
  170. #define L_VB    (L_CO|L_SY)    /* Log with both. */
  171.  
  172. /* ascii values for the `action' field. */
  173. struct actions {
  174.   char *name;
  175.   int act;
  176. } actions[] = {
  177.   { "respawn",        RESPAWN    },
  178.   { "wait",       WAIT        },
  179.   { "once",       ONCE        },
  180.   { "boot",       BOOT        },
  181.   { "bootwait",       BOOTWAIT    },
  182.   { "powerfail",   POWERFAIL    },
  183.   { "powerfailnow",POWERFAILNOW },
  184.   { "powerwait",   POWERWAIT    },
  185.   { "powerokwait", POWEROKWAIT    },
  186.   { "ctrlaltdel",  CTRLALTDEL    },
  187.   { "off",       OFF        },
  188.   { "ondemand",       ONDEMAND    },
  189.   { "initdefault", INITDEFAULT    },
  190.   { "sysinit",       SYSINIT    },
  191.   { "kbrequest",   KBREQUEST    },
  192.   { NULL,       0        },
  193. };
  194.  
  195. /*
  196.  *    Set the process title. We do not check for overflow of
  197.  *    the stack space since we know there is plenty for
  198.  *    our needs and we'll never use more than 10 bytes anyway.
  199.  */
  200. int setproctitle(char *fmt, ...)
  201. {
  202.   va_list ap;
  203.   int len;
  204.   char buf[256];
  205.  
  206.   buf[0] = 0;
  207.  
  208.   va_start(ap, fmt);
  209.   len = vsprintf(buf, fmt, ap);
  210.   va_end(ap);
  211.  
  212.   memset(argv0, 0, maxproclen + 1);
  213.   strncpy(argv0, buf, maxproclen);
  214.  
  215.   return len;
  216. }
  217.  
  218. /* Open a device with retries. */
  219. int serial_open(char *dev, int mode)
  220. {
  221.   int f, fd;
  222.   int m;
  223.  
  224.   /* Open device in nonblocking mode. */
  225.   m = mode | O_NONBLOCK;
  226.  
  227.   /* Retry the open five times. */
  228.   for(f = 0;f < 5; f++)
  229.     if ((fd = open(dev, m)) >= 0) break;
  230.   if (fd < 0) return(fd);
  231.  
  232.   /* Set original flags. */
  233.   if (m != mode)
  234.       fcntl(fd, F_SETFL, mode);
  235.   return(fd);
  236. }
  237.  
  238. /* We got a signal (HUP PWR WINCH ALRM INT) */
  239. void signal_handler(int sig)
  240. {
  241.   sigaddset(&got_signals, sig);
  242. }
  243.  
  244. /* SIGCHLD: one of our children has died. */
  245. void chld_handler()
  246. {
  247.   CHILD *ch;
  248.   int pid, st;
  249.  
  250.   /* Find out which process(es) this was (were) */
  251.   while((pid = waitpid(-1, &st, WNOHANG)) != 0) {
  252.     if (errno == ECHILD) break;
  253. #ifdef __alpha__
  254.     /* Buggy library */
  255.     if (pid == -ECHILD) break;
  256. #endif
  257.     for( ch = family; ch; ch = ch->next )
  258.         if ( ch->pid == pid && (ch->flags & RUNNING) ) {
  259. #if DEBUG
  260.             Log(L_VB, "chld_handler: marked %d as zombie", ch->pid);
  261. #endif
  262.             sigaddset(&got_signals, SIGCHLD);
  263.             ch->exstat = st;
  264.             ch->flags |= ZOMBIE;
  265.             if (ch->new) {
  266.                 ch->new->exstat = st;
  267.                 ch->new->flags |= ZOMBIE;
  268.             }
  269.             break;
  270.         }
  271. #if DEBUG
  272.     if (ch == NULL)
  273.         Log(L_VB, "chld_handler: unknown child %d exited.", pid);
  274. #endif
  275.   }
  276. }
  277.  
  278. /*
  279.  * Linux ignores all signals sent to init when the
  280.  * SIG_DFL handler is installed. Therefore we must catch SIGTSTP
  281.  * and SIGCONT, or else they won't work....
  282.  *
  283.  * The SIGCONT handler
  284.  */
  285. void cont_handler()
  286. {
  287.   got_cont = 1;
  288. }
  289.  
  290. /*
  291.  * OOPS: segmentation violation!
  292.  */
  293. void segv_handler()
  294. {
  295.   Log(L_VB, "PANIC: segmentation violation! giving up..");
  296.   while(1) pause();
  297. }
  298.  
  299. /*
  300.  * The SIGSTOP & SIGTSTP handler
  301.  */
  302. void stop_handler()
  303. {
  304.   got_cont = 0;
  305.   while(!got_cont) pause();
  306.   got_cont = 0;
  307. }
  308.  
  309. /* Set terminal settings to reasonable defaults */
  310. void SetTerm(int how)
  311. {
  312.   struct termios tty;
  313.   int fd, fd2;
  314.   int restore_ok = 0;
  315.  
  316.   if ((fd = serial_open(console_dev, O_RDWR|O_NOCTTY)) < 0) {
  317.     Log(L_VB, "can't open %s", console_dev);
  318.     return;
  319.   }
  320.  
  321.   /* Do we want to save or restore modes. */
  322.   if (how == 0) {
  323.     /* Restore. */
  324.     if (wroteiosave && (fd2 = open(IOSAVE, O_RDONLY)) >= 0) {
  325.         if (read(fd2, &tty, sizeof(tty)) == sizeof(tty))
  326.             restore_ok = 1;
  327.         close(fd2);
  328.     }
  329.     if (restore_ok == 0) {
  330.         /* Get old settings */
  331.         (void) ioctl(fd, TCGETS, &tty);
  332.  
  333.         /* Set speed etc. */
  334.         tty.c_cflag &= CBAUD|CBAUDEX|CSIZE|CSTOPB|PARENB|PARODD;
  335.         tty.c_cflag |= HUPCL|CLOCAL;
  336.         /* FIXME: should we set C_LINE here? */
  337.  
  338.         /* Set the most important characters */
  339.         tty.c_cc[VINTR]  = 3;
  340.         tty.c_cc[VQUIT]  = 28;
  341.         tty.c_cc[VERASE] = 127;
  342.         tty.c_cc[VKILL]  = 24;
  343.         tty.c_cc[VEOF]   = 4;
  344.         tty.c_cc[VTIME]  = 0;
  345.         tty.c_cc[VMIN]   = 1;
  346.         tty.c_cc[VSTART] = 17;
  347.         tty.c_cc[VSTOP]  = 19;
  348.         tty.c_cc[VSUSP]  = 26;
  349.     }
  350.  
  351.     /* Set pre and post processing */
  352.     tty.c_iflag = IGNPAR|ICRNL|IXON|IXANY;
  353.     tty.c_oflag = OPOST|ONLCR;
  354.     tty.c_lflag = ISIG|ICANON|ECHO|ECHOCTL|ECHOPRT|ECHOKE;
  355.  
  356.     /* Now set the terminal line. */
  357.     (void) ioctl(fd, TCSETS, &tty);
  358.     (void) close(fd);
  359.     return;
  360.   }
  361.  
  362.   /* Save the terminal settings. */
  363.   (void) ioctl(fd, TCGETS, &tty);
  364.   if ((fd2 = open(IOSAVE, O_WRONLY|O_CREAT|O_TRUNC, 0600)) < 0) {
  365.     if (errno != EROFS)
  366.         Log(L_VB, "can't open(%s, O_WRONLY): %s", IOSAVE, sys_errlist[errno]);
  367.     (void) close(fd);
  368.     (void) close(fd2);
  369.     return;
  370.   }
  371.   (void) write(fd2, &tty, sizeof(struct termios));
  372.   wroteiosave = 1;
  373.   (void) close(fd);
  374.   (void) close(fd2);
  375. }
  376.  
  377. /* Print to the system console */
  378. void print(char *s)
  379. {
  380.   int fd;
  381.  
  382.   if ((fd = serial_open(console_dev, O_WRONLY|O_NOCTTY|O_NDELAY)) >= 0) {
  383.     write(fd, s, strlen(s));
  384.     close(fd);
  385.   }
  386. }
  387.  
  388. /* Sleep a number of seconds */
  389. void Sleep(int sec)
  390. {
  391.   int oldAlrm;            /* Previous value of timer */
  392.   int f;            /* Counter */
  393.   int ga = sigismember(&got_signals, SIGALRM);    /* Remember got_alrm flag */
  394.  
  395.   /* Save old alarm time */
  396.   oldAlrm = alarm(0);
  397.  
  398.   /* Wait 'sec' seconds */
  399.   for(f = 0; f < sec; f++) {
  400.     sigdelset(&got_signals, SIGALRM);
  401.     alarm(1);
  402.     while(sigismember(&got_signals, SIGALRM) == 0) pause();
  403.   }
  404.  
  405.   /* Reset old values of got_alrm flag and the timer */
  406.   ga ? sigaddset(&got_signals, SIGALRM) : sigdelset(&got_signals, SIGALRM);
  407.   if (oldAlrm) alarm(oldAlrm - sec > 0 ? oldAlrm - sec : 1);
  408. }
  409.  
  410. /* Log something to the user */
  411. void Log(int loglevel, char *s, ...)
  412. {
  413.   va_list va_alist;
  414.   char buf[256];
  415.  
  416.   va_start(va_alist, s);
  417.   vsprintf(buf, s, va_alist);
  418.   va_end(va_alist);
  419.  
  420. #if SYSLOG
  421.   if (loglevel & L_SY) {
  422.     /* Re-etablish connection with syslogd every time. */
  423.     openlog("init", 0, LOG_DAEMON);
  424.     syslog(LOG_INFO, buf);
  425.     /* closelog(); NOT needed with recent libc's. */
  426.   }
  427. #endif
  428.  
  429.   /* And log to the console. */
  430.   if (loglevel & L_CO) {
  431.     print("\rINIT: ");
  432.     print(buf);
  433.     print("\r\n");
  434.   }
  435. }
  436.  
  437. /* See if one character of s2 is in s1 */
  438. int any(char *s1, char *s2)
  439. {
  440.   while(*s2)
  441.     if (strchr(s1, *s2++) != NULL) return(1);
  442.   return(0);
  443. }
  444.  
  445.  
  446. /*
  447.  * Fork and execute.
  448.  */
  449. int Spawn(CHILD *ch)
  450. {
  451.   char *args[16];        /* Argv array */
  452.   char buf[136];        /* Line buffer */
  453.   int f, pid;            /* Scratch variables */
  454.   char *ptr;            /* Ditto */
  455.   time_t t;            /* System time */
  456.   int oldAlarm;            /* Previous alarm value */
  457.   char *proc = ch->process;    /* Command line */
  458.   char i_lvl[] = "RUNLEVEL=x";    /* Runlevel in environment. */
  459.   char i_prev[] = "PREVLEVEL=x";/* Previous runlevel. */
  460.   char i_cons[32];        /* console device. */
  461.  
  462.   /* Skip '+' if it's there */
  463.   if (proc[0] == '+') proc++;
  464.  
  465.   ch->flags |= XECUTED;
  466.  
  467.   if (ch->action == RESPAWN || ch->action == ONDEMAND) {
  468.     /* Is the date stamp from less than 2 minutes ago? */
  469.     time(&t);
  470.     if (ch->tm + TESTTIME > t)
  471.         ch->count++;
  472.     else
  473.         ch->count = 0;
  474.     ch->tm = t;
  475.  
  476.     /* Do we try to respawn too fast? */
  477.     if (ch->count >= MAXSPAWN) {
  478.  
  479.       Log(L_VB, "Id \"%s\" respawning too fast: disabled for %d minutes",
  480.             ch->id, SLEEPTIME / 60);
  481.       ch->flags &= ~RUNNING;
  482.       ch->flags |= FAILING;
  483.  
  484.       /* Remember the time we stopped */
  485.       ch->tm = t;
  486.  
  487.       /* Try again in 5 minutes */
  488.       oldAlarm = alarm(0);
  489.       if (oldAlarm > SLEEPTIME || oldAlarm <= 0) oldAlarm = SLEEPTIME;
  490.       alarm(oldAlarm);
  491.       return(-1);
  492.     }
  493.   }
  494.  
  495.   /* See if there is an "initscript" (except in single user mode). */
  496.   if (access(INITSCRIPT, R_OK) == 0 && runlevel != 'S') {
  497.     /* Build command line using "initscript" */
  498.     args[1] = SHELL;
  499.     args[2] = INITSCRIPT;
  500.     args[3] = ch->id;
  501.     args[4] = ch->rlevel;
  502.     args[5] = "unknown";
  503.     for(f = 0; actions[f].name; f++) {
  504.         if (ch->action == actions[f].act) {
  505.             args[5] = actions[f].name;
  506.             break;
  507.         }
  508.     }
  509.     args[6] = proc;
  510.     args[7] = NULL;
  511.   } else if (any(proc, "~`!$^&*()=|\\{}[];\"'<>?")) {
  512.   /* See if we need to fire off a shell for this command */
  513.       /* Give command line to shell */
  514.       args[1] = SHELL;
  515.       args[2] = "-c";
  516.       strcpy(buf, "exec ");
  517.       strcat(buf, proc);
  518.       args[3] = buf;
  519.       args[4] = NULL;
  520.   } else {
  521.     /* Split up command line arguments */
  522.       strcpy(buf, proc);
  523.       ptr = buf;
  524.       for(f = 1; f < 15; f++) {
  525.           /* Skip white space */
  526.           while(*ptr == ' ' || *ptr == '\t') ptr++;
  527.           args[f] = ptr;
  528.           
  529.         /* May be trailing space.. */
  530.         if (*ptr == 0) break;
  531.  
  532.           /* Skip this `word' */
  533.           while(*ptr && *ptr != ' ' && *ptr != '\t' && *ptr != '#')
  534.               ptr++;
  535.           
  536.           /* If end-of-line, break */    
  537.           if (*ptr == '#' || *ptr == 0) {
  538.               f++;
  539.               *ptr = 0;
  540.               break;
  541.           }
  542.           /* End word with \0 and continue */
  543.           *ptr++ = 0;
  544.       }
  545.       args[f] = NULL;
  546.   }
  547.   args[0] = args[1];
  548.   while(1) {
  549.     if ((pid = fork()) == 0) {
  550.         close(PIPE_FD);
  551. #if DEBUG && !SYSLOG
  552.         pid = open("/dev/null", O_RDONLY);
  553.         close(pid);
  554.         if (pid != 0)
  555.             Log(L_VB, "some fd is still open (%d)", pid);
  556. #endif
  557.         /* Now set RUNLEVEL and PREVLEVEL */
  558.         sprintf(i_cons, "CONSOLE=%s", console_dev);
  559.         i_lvl[9]   = thislevel;
  560.         i_prev[10] = prevlevel;
  561.         putenv(i_lvl);
  562.         putenv(i_prev);
  563.         putenv(i_cons);
  564.         putenv(E_VERSION);
  565.  
  566.           /* The single user entry needs to talk to the console */
  567.           if (strcmp(ch->rlevel, "S") == 0) {
  568.             setsid();
  569.             f = serial_open(console_dev, O_RDWR);
  570.             ioctl(f, TIOCSCTTY, (void *)1);
  571.               dup(f);
  572.               dup(f);
  573.             /* Set ioctl settings to default ones */
  574.             SetTerm(0);
  575.           } else {
  576.             if ((f = serial_open(console_dev, O_RDWR|O_NOCTTY)) < 0) {
  577.                 Log(L_VB, "open(%s): %s", console_dev,
  578.                     sys_errlist[errno]);
  579.                 f = open("/dev/null", O_RDWR);
  580.             }
  581.             dup(f);
  582.             dup(f);
  583.             setsid();
  584.         }
  585.           /* Reset all the signals */
  586.           for(f = 1; f < _NSIG; f++) signal(f, SIG_DFL);
  587.           execvp(args[1], args + 1);
  588.         /* Is this a bug in execvp? It does _not_ execute shell
  589.          * scripts (/etc/rc !), so we try again with 'sh -c exec ...'
  590.          */
  591.         if (errno == ENOEXEC) {
  592.               args[1] = SHELL;
  593.               args[2] = "-c";
  594.               strcpy(buf, "exec ");
  595.               strcat(buf, proc);
  596.               args[3] = buf;
  597.               args[4] = NULL;
  598.             execvp(args[1], args + 1);
  599.         }
  600.           Log(L_VB, "cannot execute \"%s\"", args[1]);
  601.           exit(1);
  602.       }
  603. #if DEBUG
  604.     Log(L_VB, "Started id %s (pid %d)", ch->id, pid);
  605. #endif
  606.  
  607.     if (pid == -1) {
  608.         Log(L_VB, "cannot fork, retry..", NULL, NULL);
  609.         Sleep(5);
  610.         continue;
  611.     }
  612.     return(pid);
  613.   }
  614. }
  615.  
  616. /* Start a child running! */
  617. void StartUp(CHILD *ch)
  618. {
  619.   /* See if it's disabled */
  620.   if (ch->flags & FAILING) return;
  621.  
  622.   switch(ch->action) {
  623.  
  624.     case SYSINIT:
  625.       case BOOTWAIT:
  626.     case WAIT:
  627.     case POWERWAIT:
  628.     case POWERFAILNOW:
  629.     case POWEROKWAIT:
  630.     case CTRLALTDEL:
  631.         if (!(ch->flags & XECUTED)) ch->flags |= WAITING;
  632.     case KBREQUEST:
  633.     case BOOT:
  634.     case POWERFAIL:
  635.     case ONCE:
  636.         if (ch->flags & XECUTED) break;
  637.     case ONDEMAND:
  638.     case RESPAWN:
  639.           ch->flags |= RUNNING;
  640.           if ((ch->pid = Spawn(ch)) < 0) break;
  641.         /* Do NOT log if process field starts with '+' */
  642.           if (ch->process[0] != '+')
  643.             Wtmp("", ch->id, ch->pid, INIT_PROCESS, "");
  644.           break;
  645.   }
  646. }
  647.  
  648. /* My version of strtok(3) */
  649. char *getPart(char *str, int tok)
  650. {
  651.   static char *s;
  652.   char *p, *q;
  653.  
  654.   if (str != NULL) s = str;
  655.   if (s == NULL || *s == 0) return(NULL);
  656.   q = p = s;
  657.   while(*p != tok && *p) p++;
  658.   if (*p == tok) *p++ = 0;
  659.   s = p;
  660.   return(q);
  661. }
  662.  
  663. /* Read the inittab file. */
  664. void ReadItab(void)
  665. {
  666.   FILE *fp;            /* The INITTAB file */
  667.   char buf[256];        /* Line buffer */
  668.   char err[64];            /* Error message. */
  669.   char *id, *rlevel,
  670.        *action, *process;    /* Fields of a line */
  671.   CHILD *ch, *old, *i;        /* Pointers to CHILD structure */
  672.   CHILD *head = NULL;        /* Head of linked list */
  673.   int lineNo = 0;        /* Line number in INITTAB file */
  674.   int actionNo;            /* Decoded action field */
  675.   int f;            /* Counter */
  676.   int round;            /* round 0 for SIGTERM, round 1 for SIGKILL */
  677.   int foundOne = 0;        /* No killing no sleep */
  678.   int talk;            /* Talk to the user */
  679.   int done = 0;            /* Ready yet? */
  680.   sigset_t omask;        /* For blocking SIGCHLD. */
  681.   struct stat st;        /* To stat INITLVL */
  682.  
  683. #if DEBUG
  684.   if (newFamily != NULL) {
  685.     Log(L_VB, "PANIC newFamily != NULL");
  686.     exit(1);
  687.   }
  688.   Log(L_VB, "Reading inittab");
  689. #endif
  690.  
  691.   /* Open INITTAB */
  692.   if ((fp = fopen(INITTAB, "r")) == NULL)
  693.     Log(L_VB, "No inittab file found");
  694.  
  695.   /* Read INITTAB line by line */
  696.   while(!done) {
  697.     /* Add single user shell entry as last one. */
  698.     if (fp == NULL || fgets(buf, 255, fp) == NULL) {
  699.         done = 1;
  700.         /* See if we have a single user entry. */
  701.         for(old = newFamily; old; old = old->next)
  702.             if (strcmp(old->rlevel, "S") == 0) break;
  703.         if (old == NULL)
  704.             sprintf(buf, "~~:S:wait:%s\n", SHELL);
  705.         else
  706.             continue;
  707.     }
  708.     lineNo++;
  709.     /* Skip comments and empty lines */
  710.     if (buf[0] == '#' || buf[0] == '\n') continue;
  711.  
  712.     /* Decode the fields */
  713.     id =      getPart(buf,  ':');
  714.     rlevel =  getPart(NULL, ':');
  715.     action =  getPart(NULL, ':');
  716.     process = getPart(NULL, '\n');
  717.  
  718.     /* Check if syntax is OK. Be very verbose here, to
  719.      * avoid newbie postings on comp.os.linux.setup :)
  720.      */
  721.     err[0] = 0;
  722.     if (!id || !*id) strcpy(err, "missing id field");
  723.     if (!rlevel)     strcpy(err, "missing runlevel field");
  724.     if (!process)    strcpy(err, "missing process field");
  725.     if (!action && !*action)
  726.             strcpy(err, "missing action field");
  727.     if (id && strlen(id) > sizeof(utproto.ut_id))
  728.             sprintf(err, "id field too long (max %d characters)",
  729.                 sizeof(utproto.ut_id));
  730.     if (rlevel && strlen(rlevel) > 11)
  731.             strcpy(err, "rlevel field too long (max 11 characters)");
  732.     if (process && strlen(process) > 127) strcpy(err, "process field too long");
  733.     if (err[0] != 0) {
  734.         Log(L_VB, "%s[%d]: %s", INITTAB, lineNo, err);
  735. #if DEBUG
  736.         Log(L_VB, "%s:%s:%s:%s", id, rlevel, action, process);
  737. #endif
  738.         continue;
  739.     }
  740.   
  741.     /* Decode the "action" field */
  742.     actionNo = -1;
  743.     for(f = 0; actions[f].name; f++)
  744.         if (strcasecmp(action, actions[f].name) == 0) {
  745.             actionNo = actions[f].act;
  746.             break;
  747.         }
  748.     if (actionNo == -1) {
  749.         Log(L_VB, "%s[%d]: %s: unknown action field",
  750.             INITTAB, lineNo, action);
  751.         continue;
  752.     }
  753.  
  754.     /* See if the id field is unique */
  755.     for(old = newFamily; old; old = old->next) {
  756.         if(strcmp(old->id, id) == 0 && strcmp(id, "~~")) {
  757.             Log(L_VB, "%s[%d]: duplicate ID field \"%s\"",
  758.                 INITTAB, lineNo, id);
  759.             break;
  760.         }
  761.     }
  762.     if (old) continue;
  763.  
  764.     /* Allocate a CHILD structure */
  765.     if ((ch = malloc(sizeof(CHILD))) == NULL) {
  766.         Log(L_VB, "out of memory");
  767.         continue;
  768.     }
  769.     memset(ch, 0, sizeof(CHILD));
  770.  
  771.     /* And fill it in. */
  772.     ch->action = actionNo;
  773.     strncpy(ch->id, id, sizeof(utproto.ut_id) + 1); /* Hack for different libs. */
  774.     strncpy(ch->process, process, 127);
  775.     if (rlevel[0]) {
  776.         for(f = 0; f < 11 && rlevel[f]; f++) {
  777.             ch->rlevel[f] = rlevel[f];
  778.             if (ch->rlevel[f] == 's') ch->rlevel[f] = 'S';
  779.         }
  780.         strncpy(ch->rlevel, rlevel, 11);
  781.     } else {
  782.         strcpy(ch->rlevel, "0123456789");
  783.         if (ISPOWER(ch->action))
  784.             strcpy(ch->rlevel, "S0123456789");
  785.     }
  786.     /*
  787.      * We have the fake runlevel '#' for SYSINIT  and
  788.      * '*' for BOOT and BOOTWAIT.
  789.      */
  790.     if (ch->action == SYSINIT) strcpy(ch->rlevel, "#");
  791.     if (ch->action == BOOT || ch->action == BOOTWAIT)
  792.         strcpy(ch->rlevel, "*");
  793.  
  794.     /* Now add it to the linked list. Special for powerfail. */
  795.     if (ISPOWER(ch->action)) {
  796.  
  797.         /* Disable by default */
  798.         ch->flags |= XECUTED;
  799.  
  800.         /* Tricky: insert at the front of the list.. */
  801.         old = NULL;
  802.         for(i = newFamily; i; i = i->next) {
  803.             if (!ISPOWER(i->action)) break;
  804.             old = i;
  805.         }
  806.         /* Now add after entry "old" */
  807.         if (old) {
  808.             ch->next = i;
  809.             old->next = ch;
  810.             if (i == NULL) head = ch;
  811.         } else {
  812.             ch->next = newFamily;
  813.             newFamily = ch;
  814.             if (ch->next == NULL) head = ch;
  815.         }
  816.     } else {
  817.         /* Just add at end of the list */
  818.         if (ch->action == KBREQUEST) ch->flags |= XECUTED;
  819.         ch->next = NULL;
  820.         if (head)
  821.             head->next = ch;
  822.         else
  823.             newFamily = ch;
  824.         head = ch;
  825.     }
  826.  
  827.     /* Walk through the old list comparing id fields */
  828.     for(old = family; old; old = old->next)
  829.         if (strcmp(old->id, ch->id) == 0) {
  830.             old->new = ch;
  831.             break;
  832.         }
  833.   }
  834.   /* We're done. */
  835.   if (fp) fclose(fp);
  836.  
  837.   /*
  838.    * Loop through the list of children, and see if they need to
  839.    * be killed. 
  840.    */
  841.  
  842. #if DEBUG
  843.   Log(L_VB, "Checking for children to kill");
  844. #endif
  845.   for(round = 0; round < 2; round++) {
  846.     talk = 1;
  847.     for(ch = family; ch; ch = ch->next) {
  848.     ch->flags &= ~KILLME;
  849.  
  850.     /* Is this line deleted? */
  851.     if (ch->new == NULL) ch->flags |= KILLME;
  852.  
  853. #if 0 /* XXX - This is more compatible with real sysv. */
  854.     /* See if the entry changed. Yes: kill anyway */
  855.     if (ch->new && (strcmp(ch->process, ch->new->process) ||
  856.         ch->action != ch->new->action)) ch->flags |= KILLME;
  857. #endif
  858.  
  859.     /* Only BOOT processes may live in all levels */
  860.     if (ch->action != BOOT &&
  861.         strchr(ch->rlevel, runlevel) == NULL) {
  862.         /* Ondemand procedures live always except in single user */
  863.         if (runlevel == 'S' || !(ch->flags & DEMAND))
  864.             ch->flags |= KILLME;
  865.     }
  866.  
  867.     /* Now, if this process may live note so in the new list */
  868.     if ((ch->flags & KILLME) == 0) {
  869.         ch->new->flags  = ch->flags;
  870.         ch->new->pid    = ch->pid;
  871.         ch->new->exstat = ch->exstat;
  872.         continue;
  873.     }
  874.  
  875.  
  876.     /* Is this process still around? */
  877.     if ((ch->flags & RUNNING) == 0) {
  878.         ch->flags &= ~KILLME;
  879.         continue;
  880.     }
  881. #if DEBUG
  882.     Log(L_VB, "Killing \"%s\"", ch->process);
  883. #endif
  884.     switch(round) {
  885.         case 0: /* Send TERM signal */
  886.             if (talk)
  887.                 Log(L_CO, "Sending processes the TERM signal");
  888.             kill(-(ch->pid), SIGTERM);
  889.             foundOne = 1;
  890.             break;
  891.         case 1: /* Send KILL signal and collect status */
  892.             if (talk)
  893.                 Log(L_CO, "Sending processes the KILL signal");
  894.             kill(-(ch->pid), SIGKILL);
  895.             break;
  896.     }
  897.     talk = 0;
  898.     
  899.     /* And process the next member of our family */
  900.     }
  901.     /* See if we have to wait 5 seconds */
  902.     if (foundOne && round == 0) {
  903.     /* Yup, but check every second if we still have children. */
  904.     for(f = 0; f < sltime; f++) {
  905.         for(ch = family; ch; ch = ch->next) {
  906.             if (!(ch->flags & KILLME)) continue;
  907.             if ((ch->flags & RUNNING) && !(ch->flags & ZOMBIE))
  908.                 break;
  909.         }
  910.         if (ch == NULL) {
  911.             /* No running children, skip SIGKILL */
  912.             round = 1;
  913.             foundOne = 0; /* Skip the sleep below. */
  914.             break;
  915.         }
  916.         Sleep(1);
  917.     }
  918.     }
  919.   }
  920.  
  921.   /* Now give all processes the chance to die and collect exit statuses */
  922.   /* FIXME: how to give away time slice?? */
  923.   if (foundOne) Sleep(1);
  924.   for(ch = family; ch; ch = ch->next)
  925.     if (ch->flags & KILLME) {
  926.         if (!(ch->flags & ZOMBIE))
  927.             Log(L_CO, "Pid %d [id %s] seems to hang", ch->pid,
  928.                 ch->id);
  929.         else {
  930. #if DEBUG
  931.             Log(L_VB, "Updating utmp for pid %d [id %s]", ch->pid, ch->id);
  932. #endif
  933.             ch->flags &= ~RUNNING;
  934.             if (ch->process[0] != '+')
  935.                 Wtmp("", ch->id, ch->pid, DEAD_PROCESS, NULL);
  936.         }
  937.     }
  938.  
  939.   /* Both rounds done; clean up the list. */
  940.   omask = siggetmask();
  941.   sigblock(sigmask(SIGCHLD));
  942.   for(ch = family; ch; ch = old) {
  943.     old = ch->next;
  944.     free(ch);
  945.   }
  946.   family = newFamily;
  947.   for(ch = family; ch; ch = ch->next) ch->new = NULL;
  948.   newFamily = NULL;
  949.   sigsetmask(omask);
  950.  
  951.   /* Dispose of INITLVL file. */
  952.   if (lstat(INITLVL, &st) >= 0 && S_ISLNK(st.st_mode)) {
  953.     /* INITLVL is a symbolic link, so just truncate the file. */
  954.     close(open(INITLVL, O_WRONLY|O_TRUNC));
  955.   } else {
  956.     /* Delete INITLVL file. */
  957.       unlink(INITLVL);
  958.   }
  959. }
  960.  
  961. /*
  962.  * Walk through the family list and start up children.
  963.  * The entries that do not belong here at all are removed
  964.  * from the list.
  965.  */
  966. void StartEmIfNeeded(void)
  967. {
  968.   CHILD *ch;        /* Pointer to child */
  969.   int delete;        /* Delete this entry from list? */
  970.  
  971. #if DEBUG
  972.   Log(L_VB, "Checking for children to start");
  973. #endif
  974.  
  975.   for(ch = family; ch; ch = ch->next) {
  976.  
  977. #if DEBUG
  978.     if (ch->rlevel[0] == 'C') {
  979.         Log(L_VB, "%s: flags %d", ch->process, ch->flags);
  980.     }
  981. #endif
  982.  
  983.     /* Are we waiting for this process? Then quit here. */
  984.     if (ch->flags & WAITING) break;
  985.  
  986.     /* Already running? OK, don't touch it */
  987.     if (ch->flags & RUNNING) continue;
  988.  
  989.     /* See if we have to start it up */
  990.     delete = 1;
  991.     if (strchr(ch->rlevel, runlevel) ||
  992.         ((ch->flags & DEMAND) && !strchr("#*Ss", runlevel))) {
  993.         StartUp(ch);
  994.         delete = 0;
  995.     }
  996.  
  997.     if (delete) {
  998.         /* FIXME: is this OK? */
  999.         ch->flags &= ~(RUNNING|WAITING);
  1000.         if (!ISPOWER(ch->action) && ch->action != KBREQUEST)
  1001.             ch->flags &= ~XECUTED;
  1002.         ch->pid = 0;
  1003.     } else
  1004.         /* Do we have to wait for this process? */
  1005.         if (ch->flags & WAITING) break;
  1006.   }
  1007.   /* Done. */
  1008. }
  1009.  
  1010. /*
  1011.  * Ask the user on the console for a runlevel
  1012.  */
  1013. int AskRunLevel()
  1014. {
  1015.   int lvl = -1;
  1016.   char buf[8];
  1017.   int fd;
  1018.  
  1019.  
  1020.   SetTerm(0);
  1021.   fd = serial_open(console_dev, O_RDWR|O_NOCTTY);
  1022.     /* FIXME as soon as O_NDELAY != O_NONBLOCK */
  1023.   if (fd < 0) return('S');
  1024.  
  1025.   while(!strchr("0123456789S", lvl)) {
  1026.       write(fd, "\nEnter runlevel: ", 17);
  1027.     buf[0] = 0;
  1028.       read(fd, buf, 8);
  1029.       if (buf[0] != 0 && (buf[1] == '\r' || buf[1] == '\n')) lvl = buf[0];
  1030.     if (islower(lvl)) lvl = toupper(lvl);
  1031.   }
  1032.   close(fd);
  1033.   return(lvl);
  1034. }
  1035.  
  1036. /*
  1037.  * Search the INITTAB file for the 'initdefault' field, with the default
  1038.  * runlevel. If this fails, ask the user to supply a runlevel.
  1039.  */
  1040. int GetInitDefault(void)
  1041. {
  1042.   CHILD *ch;
  1043.   int lvl = -1;
  1044.   char *p;
  1045.  
  1046.   /* Look for initdefault. */
  1047.   for(ch = family; ch; ch = ch->next)
  1048.     if (ch->action == INITDEFAULT) {
  1049.         p = ch->rlevel;
  1050.         while(*p) {
  1051.             if (*p > lvl) lvl = *p;
  1052.             p++;
  1053.         }
  1054.         break;
  1055.     }
  1056.   /* See if level is valid */
  1057.   if (lvl > 0) {
  1058.     if (islower(lvl)) lvl = toupper(lvl);
  1059.     if (strchr("0123456789S", lvl) == NULL) {
  1060.         Log(L_VB, "Initdefault level '%c' is invalid", lvl);
  1061.         lvl = 0;
  1062.     }
  1063.   }
  1064.   /* Ask for runlevel on console if needed. */
  1065.   if (lvl <= 0) lvl = AskRunLevel();
  1066.  
  1067.   /* Log the fact that we have a runlevel now. */
  1068.   return(lvl);
  1069. }
  1070.  
  1071.  
  1072. /*
  1073.  * We got signaled: read the new level from INITLVL
  1074.  */
  1075. int ReadLevel(int arg)
  1076. {
  1077.   unsigned char foo = 'X';        /* Contents of INITLVL */
  1078.   int st;                /* Sleep time */
  1079.   CHILD *ch;                /* Walk through list */
  1080.   FILE *fp;                /* File pointer for INITLVL */
  1081.   int ok = 0;
  1082.   struct stat stt;
  1083.  
  1084. #if CLEAN_UTMP
  1085.   /* Clean up utmp file first. */
  1086.   Wtmp(NULL, "", -2, 0, NULL);
  1087. #endif
  1088.  
  1089.   if (arg == 0) {
  1090.     if ((fp = fopen(INITLVL, "r")) == NULL ||
  1091.           (stat(INITLVL, &stt) == 0 && stt.st_size == 0L)) {
  1092.         /* INITLVL file is empty or not there - act as 'init q' */
  1093.         Log(L_SY, "Re-reading inittab");
  1094.           return(runlevel);
  1095.     }
  1096.     ok = fscanf(fp, "%c %d", &foo, &st);
  1097.     fclose(fp);
  1098.   } else {
  1099.     /* We go to the new runlevel passed as an argument. */
  1100.     foo = arg;
  1101.     ok = 1;
  1102.   }
  1103.   if (islower(foo)) foo = toupper(foo);
  1104.  
  1105.   if (ok < 1 || ok > 2 || strchr("QS0123456789ABC", foo) == NULL) {
  1106.      Log(L_VB, "bad runlevel: %c", foo);
  1107.       return(runlevel);
  1108.   }
  1109.   if (ok == 2) sltime = st;
  1110.  
  1111.   /* Be verbose 'bout it all */
  1112.   switch(foo) {
  1113.     case 'S':
  1114.           Log(L_VB, "Going single user");
  1115.         break;
  1116.     case 'Q':
  1117.         Log(L_SY, "Re-reading inittab");
  1118.         break;
  1119.     case 'A':
  1120.     case 'B':
  1121.     case 'C':
  1122.         Log(L_SY, "Activating demand-procedures for '%c'", foo);
  1123.         break;
  1124.     default:
  1125.           Log(L_VB, "Switching to runlevel: %c", foo);
  1126.   }
  1127.  
  1128.   if (foo == 'Q') return(runlevel);
  1129.  
  1130.   /* Check if this is a runlevel a, b or c */
  1131.   if (strchr("ABC", foo)) {
  1132.     if (runlevel == 'S') return(runlevel);
  1133.  
  1134.     /* Read inittab again first! */
  1135.     ReadItab();
  1136.  
  1137.       /* Mark those special tasks */
  1138.     for(ch = family; ch; ch = ch->next)
  1139.         if (strchr(ch->rlevel, foo) != NULL ||
  1140.             strchr(ch->rlevel, tolower(foo)) != NULL) {
  1141.             ch->flags |= DEMAND;
  1142.             ch->flags &= ~XECUTED;
  1143. #if DEBUG
  1144.             Log(L_VB, "Marking (%s) as ondemand, flags %d",
  1145.                 ch->id, ch->flags);
  1146. #endif
  1147.         }
  1148.       return(runlevel);
  1149.   }
  1150.  
  1151.   /* Store both the old and the new runlevel. */
  1152.   Wtmp("runlevel", "~~", foo + 256*runlevel, RUN_LVL, "~");
  1153.   thislevel = foo;
  1154.   prevlevel = runlevel;
  1155.   return(foo);
  1156. }
  1157.  
  1158.  
  1159. /*
  1160.  * Zero out an utmp struct but copy the id field.
  1161.  */
  1162. void EmptyStruct(struct utmp *oldu, struct utmp *newu)
  1163. {
  1164.   memset(newu, 0, sizeof(struct utmp));
  1165.   strncpy(newu->ut_id, oldu->ut_id, sizeof(newu->ut_id));
  1166.   strncpy(newu->ut_line, oldu->ut_line, sizeof(newu->ut_line));
  1167.   newu->ut_type = DEAD_PROCESS;
  1168. }
  1169.  
  1170. /*
  1171.  * Log an event ONLY in the wtmp file (reboot, runlevel)
  1172.  */
  1173. void WtmpOnly(
  1174. char *user,            /* name of user */
  1175. char *id,            /* inittab ID */
  1176. int pid,            /* PID of process */
  1177. int type,            /* TYPE of entry */
  1178. char *line)            /* Which line is this */
  1179. {
  1180.   int fd;
  1181.   struct utmp utmp;
  1182.   time_t t;
  1183.  
  1184.   if ((fd = open(WTMP_FILE, O_WRONLY|O_APPEND)) < 0) return;
  1185.  
  1186.   /* Note if we are going to write a boot record. */
  1187.   if (type == BOOT_TIME) wroteReboot++;
  1188.  
  1189.   /*
  1190.    * See if we need to write a reboot record. The reason that
  1191.    * we are being so paranoid is that when we first tried to
  1192.    * write the reboot record, /var was possibly not mounted
  1193.    * yet. As soon as we can open WTMP we write a delayed boot record.
  1194.    */
  1195.   if (wroteReboot == 0 && type != BOOT_TIME)
  1196.       WtmpOnly("reboot", "~~", 0, BOOT_TIME, "~");
  1197.  
  1198.   /* Zero the fields */
  1199.   memset(&utmp, 0, sizeof(utmp));
  1200.  
  1201.   /* Enter new fields */
  1202.   time(&t);
  1203.   utmp.ut_time = t;
  1204.   utmp.ut_pid  = pid;
  1205.   utmp.ut_type = type;
  1206.   strncpy(utmp.ut_name, user, sizeof(utmp.ut_name));
  1207.   strncpy(utmp.ut_id  , id  , sizeof(utmp.ut_id  ));
  1208.   strncpy(utmp.ut_line, line, sizeof(utmp.ut_line));
  1209.  
  1210.   write(fd, (char *)&utmp, sizeof(utmp));
  1211.   close(fd);
  1212. }
  1213.  
  1214. /*
  1215.  * Log an event into the WTMP and UTMP files.
  1216.  *
  1217.  * FIXME: we shouldn't zero out other processes' utmp entries. What we
  1218.  *        should do to get/update an utmp entry:
  1219.  *        o see if an entry with matching ut_id field is present
  1220.  *        o if so, re-use it.
  1221.  *        o if not, re-open utmp in O_APPEND mode and add new entry.
  1222.  *
  1223.  * Thanks to Michael Haardt for pointing this out.
  1224.  *
  1225.  * Also, check if the RUNLEVEL entry is still present and rewrite if
  1226.  * it is missing. (People tend to mess up their utmp files).
  1227.  *
  1228.  */
  1229. void Wtmp(
  1230. char *user,            /* name of user */
  1231. char *id,            /* inittab ID */
  1232. int pid,            /* PID of process */
  1233. int type,            /* TYPE of entry */
  1234. char *line)            /* LINE if used. */
  1235. {
  1236.   struct utmp utmp;        /* UTMP/WTMP User Accounting */
  1237.   struct utmp tmp;        /* Scratch */
  1238.   struct utmp empty;        /* Empty utmp struct */
  1239.   int fd = -1;            /* File Descriptor for UTMP */
  1240.   int fd2;            /* File Descriptor for WTMP */
  1241.   int found = 0;        /* Was the record found in UTMP */
  1242.   int freeEntry = -1;        /* Was a free entry found during UTMP scan? */
  1243.   int matchEntry = -1;        /* Was a matching entry found ? */
  1244.   int lineno;            /* Offset into UTMP file */
  1245.   time_t t;            /* What's the time? */
  1246.   static int opened = 0;    /* Already opened /var/run/utmp? */
  1247. #if CLEAN_UTMP
  1248.   CHILD *ch;            /* Scratch */
  1249. #endif
  1250.  
  1251.   /* Clear utmp if not yet opened. */
  1252.   if (!opened) close(open(UTMP_FILE, O_WRONLY|O_CREAT|O_TRUNC, 0644));
  1253.  
  1254.   /* First read the utmp entry for this process */
  1255.   if ((fd = open(UTMP_FILE, O_RDWR)) >= 0) {
  1256.     lineno = 0;
  1257.     opened = 1;
  1258.         while (read(fd, (char *) &tmp, sizeof(tmp)) == sizeof(tmp)) {
  1259. #if DEBUG
  1260.         Log(L_VB, "utmp #%d: pid %d, type %d", lineno / sizeof(tmp),
  1261.             tmp.ut_pid, tmp.ut_type);
  1262. #endif
  1263.         if (user != NULL &&
  1264.             ((tmp.ut_pid == pid && tmp.ut_type != NO_PROCESS) ||
  1265.              (tmp.ut_type == RUN_LVL && type == RUN_LVL))) {
  1266.             found = 1;
  1267.             memcpy(&utmp, &tmp, sizeof(utmp));
  1268.             if (type == DEAD_PROCESS) {
  1269.                 /* Zero all entries with this pid */
  1270.                 (void) lseek(fd, (long) lineno, SEEK_SET);
  1271.                 EmptyStruct(&tmp, &empty);
  1272.                 write(fd, (char *)&empty, sizeof(struct utmp));
  1273.             } else {
  1274.                 (void) lseek(fd, (long) lineno, SEEK_SET);
  1275.                 break;
  1276.             }
  1277.           }
  1278. #if CLEAN_UTMP
  1279.         /* Let's check if this process still exists. If it
  1280.          * doesn't, clear it's utmp entry.
  1281.          */
  1282.         else if (tmp.ut_type != NO_PROCESS &&
  1283.              tmp.ut_type != RUN_LVL && tmp.ut_pid > 0) {
  1284.             /* One of our children? */
  1285.             for(ch = family; ch; ch = ch->next)
  1286.                 if (ch->pid == tmp.ut_pid) break;
  1287.             if (ch == NULL && kill(tmp.ut_pid, 0) < 0) {
  1288. #if DEBUG
  1289.                 Log(L_VB, "utmp: cleaning up stale entry (pid %d)",
  1290.                     tmp.ut_pid);
  1291. #endif
  1292.                 /* Zero the entry with this pid */
  1293.                 (void) lseek(fd, (long) lineno, SEEK_SET);
  1294.                 EmptyStruct(&tmp, &empty);
  1295.                 if (write(fd, (char *)&empty, sizeof(struct utmp))
  1296.                     != sizeof(struct utmp)) {
  1297.                         Log(L_VB, "error writing utmp struct");
  1298.                         break;
  1299.                 }
  1300.             }
  1301.         }
  1302. #endif
  1303.         /* See if this is a unused entry, save it for later */
  1304.         if ((tmp.ut_pid == 0 && tmp.ut_id[0] == 0
  1305.             && tmp.ut_user[0] == 0 && tmp.ut_type != RUN_LVL) || tmp.ut_type == 0)
  1306.             if (freeEntry < 0) freeEntry = lineno;
  1307.  
  1308.         /* See if this entry is dead and matches our "id", save it for later. */
  1309.         if (tmp.ut_type == DEAD_PROCESS && strncmp(tmp.ut_id, id, sizeof(tmp.ut_id)) == 0
  1310.             && tmp.ut_user[0] == 0)
  1311.             if (matchEntry < 0) matchEntry = lineno;
  1312.  
  1313.         lineno += sizeof(tmp);
  1314.     }
  1315. #if CLEAN_UTMP
  1316.     /* Only a call to clean the utmp file? */
  1317.     if (user == NULL) {
  1318.         (void) close(fd);
  1319.         return;
  1320.     }
  1321. #endif
  1322.   }
  1323.  
  1324. #if DEBUG
  1325.   Log(L_VB, "Wtmp(): found=%d, match=%d, free=%d", found, matchEntry, freeEntry);
  1326. #endif
  1327.  
  1328.   if (!found) { /* Enter some defaults */
  1329.     /* Zero the fields */
  1330.     memset(&utmp, 0, sizeof(utmp));
  1331.  
  1332.     /* Enter new fields */
  1333.     strncpy(utmp.ut_name, user, sizeof(utmp.ut_name));
  1334.     strncpy(utmp.ut_id  , id  , sizeof(utmp.ut_id  ));
  1335.     strcpy (utmp.ut_line, "");
  1336.  
  1337.     /* Where to write new utmp record */
  1338.     if (matchEntry >= 0) freeEntry = matchEntry;
  1339.     if (freeEntry >= 0)
  1340.         lseek(fd, (long) freeEntry, SEEK_SET);
  1341.   }
  1342.  
  1343.   /* Change the values of some fields */
  1344.   time(&t);
  1345.   utmp.ut_type = type;
  1346.   utmp.ut_time = t;
  1347.   utmp.ut_pid = pid;
  1348.   if (line) strncpy(utmp.ut_line, line, sizeof(utmp.ut_line));
  1349.  
  1350.   /* Write the utmp record, if needed */
  1351.   if (fd >= 0)  {
  1352.       /* DEAD_PROCESS has already been zeroed */
  1353.       if (utmp.ut_type != DEAD_PROCESS)
  1354.         (void) write(fd, (char *) &utmp, sizeof(struct utmp));
  1355.     (void) close(fd);
  1356.   }
  1357.  
  1358.   /* Write the wtmp record */
  1359.   if ((fd2 = open(WTMP_FILE, O_WRONLY|O_APPEND)) >= 0) {
  1360.       /* See if we need to write a boot record */
  1361.     if (wroteReboot == 0 && type != BOOT_TIME) {
  1362.           WtmpOnly("reboot", "~~", 0, BOOT_TIME, "~");
  1363.         wroteReboot++;
  1364.     }
  1365.     /* Set ut_user to 0 if this is a logout record */
  1366.     if (utmp.ut_type == DEAD_PROCESS) utmp.ut_name[0] = 0;
  1367.     (void) write(fd2, (char *) &utmp, sizeof(struct utmp));
  1368.     (void) close(fd2);
  1369.   }
  1370. }
  1371.  
  1372. /*
  1373.  * This procedure is called after every signal (SIGHUP, SIGALRM..)
  1374.  *
  1375.  * Only clear the 'failing' flag if the process is sleeping
  1376.  * longer than 5 minutes, or inittab was read again due
  1377.  * to user interaction.
  1378.  */
  1379. void FailCheck(void)
  1380. {
  1381.   time_t t;        /* System time */
  1382.   CHILD *ch;        /* Pointer to child structure */
  1383.   time_t nxtAlrm = 0;    /* When to set next alarm */
  1384.  
  1385.   time(&t);
  1386.  
  1387.   for(ch = family; ch; ch = ch->next) {
  1388.  
  1389.     if (ch->flags & FAILING) {
  1390.         /* Can we free this sucker? */
  1391.         if (ch->tm + SLEEPTIME < t) {
  1392.             ch->flags &= ~FAILING;
  1393.             ch->count = 0;
  1394.             ch->tm = 0;
  1395.         } else {
  1396.             /* No, we'll look again later */
  1397.             if (nxtAlrm == 0 || ch->tm + SLEEPTIME > nxtAlrm)
  1398.                 nxtAlrm = ch->tm + SLEEPTIME;
  1399.         }
  1400.     }
  1401.   }
  1402.   if (nxtAlrm) {
  1403.     nxtAlrm -= t;
  1404.     if (nxtAlrm < 1) nxtAlrm = 1;
  1405.     alarm(nxtAlrm);
  1406.   }
  1407. }
  1408.  
  1409. /* Set all 'Fail' timers to 0 */
  1410. void FailCancel(void)
  1411. {
  1412.   CHILD *ch;
  1413.  
  1414.   for(ch = family; ch; ch = ch->next) {
  1415.     ch->count = 0;
  1416.     ch->tm = 0;
  1417.     ch->flags &= ~FAILING;
  1418.   }
  1419. }
  1420.  
  1421. /* Start up powerfail entries. */
  1422. void DoPowerFail(int pwrstat)
  1423. {
  1424.   CHILD *ch;
  1425.  
  1426.   /* Tell powerwait & powerfail entries to start up */
  1427.   for(ch = family; ch; ch = ch->next) {
  1428.     if (pwrstat == 'O') {
  1429.         /* The power is good again. */
  1430.         if (ch->action == POWEROKWAIT)
  1431.             ch->flags &= ~XECUTED;
  1432.     } else if (pwrstat == 'L') {
  1433.         /* Low battery, shut down now. */
  1434.         if (ch->action == POWERFAILNOW)
  1435.             ch->flags &= ~XECUTED;
  1436.     } else {
  1437.         /* Power is failing */
  1438.         if (ch->action == POWERFAIL || ch->action == POWERWAIT)
  1439.             ch->flags &= ~XECUTED;
  1440.     }
  1441.   }
  1442. }
  1443.  
  1444. #if NEWINIT
  1445.  
  1446. /*
  1447.  * We got a change runlevel request through the
  1448.  * init.fifo. Process it.
  1449.  */
  1450. void FifoNewLevel(int level)
  1451. {
  1452.   int oldlevel;
  1453. #if CHANGE_WAIT
  1454.   CHILD *ch;
  1455. #endif
  1456.  
  1457.   if (level == runlevel) return;
  1458.  
  1459. #if CHANGE_WAIT
  1460.   /* Are we waiting for a child? */
  1461.   for(ch = family; ch; ch = ch->next)
  1462.     if (ch->flags & WAITING) break;
  1463.   if (ch == NULL)
  1464. #endif
  1465.   {
  1466.     /* We need to go into a new runlevel */
  1467.     oldlevel = runlevel;
  1468.     runlevel = ReadLevel(level);
  1469.     if (oldlevel != 'S' && runlevel == 'S') SetTerm(0);
  1470.     if (runlevel == '6' || runlevel == '0' || runlevel == '1') SetTerm(0);
  1471.     ReadItab();
  1472.     FailCancel();
  1473.     setproctitle("init [%c]", runlevel);
  1474.   }
  1475. }
  1476.  
  1477. /*
  1478.  * Read from the init FIFO. Processes like telnetd and rlogind can
  1479.  * ask us to create login processes on their behalf.
  1480.  *
  1481.  * FIXME: this needs to be finished.
  1482.  */
  1483. void CheckInitFifo(void)
  1484. {
  1485.   static int pipe_fd = -1;
  1486.   struct init_request request;
  1487.   int n;
  1488.   fd_set fds;
  1489.   int quit = 0;
  1490.  
  1491.   /* Try to open /dev/initctl */
  1492.   if (pipe_fd < 0) {
  1493.     if ((pipe_fd = open(INIT_FIFO, O_RDWR|O_NONBLOCK)) >= 0) {
  1494.         /* Don't use fd's 0, 1 or 2. */
  1495.         (void) dup2(pipe_fd, PIPE_FD);
  1496.         close(pipe_fd);
  1497.         pipe_fd = PIPE_FD;
  1498.     }
  1499.   }
  1500.  
  1501.   /* Wait for data to appear, _if_ the pipe was opened. */
  1502.   if (pipe_fd >= 0) while(!quit) {
  1503.  
  1504.     /* Do select, return on EINTR. */
  1505.     FD_ZERO(&fds);
  1506.     FD_SET(pipe_fd, &fds);
  1507.     n = select(pipe_fd + 1, &fds, NULL, NULL, NULL);
  1508.     if (n <= 0) {
  1509.         if (errno == EINTR) return;
  1510.         continue;
  1511.     }
  1512.  
  1513.     /* Read the data, return on EINTR. */
  1514.     n = read(pipe_fd, &request, sizeof(request));
  1515.     if (n == 0) {
  1516.         /*
  1517.          *    End of file. This can't happen under Linux (because
  1518.          *    the pipe is opened O_RDWR - see select() in the
  1519.          *    kernel) but you never know...
  1520.          */
  1521.         close(pipe_fd);
  1522.         pipe_fd = -1;
  1523.         return;
  1524.     }
  1525.     if (n <= 0) {
  1526.         if (errno == EINTR) return;
  1527.         Log(L_VB, "error reading initrequest");
  1528.         continue;
  1529.     }
  1530.  
  1531.     /* Process request. */
  1532.     if (request.magic != INIT_MAGIC || n != sizeof(request)) {
  1533.         Log(L_VB, "got bogus initrequest");
  1534.         continue;
  1535.     }
  1536.     switch(request.cmd) {
  1537.         case INIT_CMD_RUNLVL:
  1538.             sltime = request.sleeptime;
  1539.             FifoNewLevel(request.runlevel);
  1540.             quit = 1;
  1541.             break;
  1542.         case INIT_CMD_POWERFAIL:
  1543.             sltime = request.sleeptime;
  1544.             DoPowerFail('F');
  1545.             quit = 1;
  1546.             break;
  1547.         case INIT_CMD_POWERFAILNOW:
  1548.             sltime = request.sleeptime;
  1549.             DoPowerFail('L');
  1550.             quit = 1;
  1551.             break;
  1552.         case INIT_CMD_POWEROK:
  1553.             sltime = request.sleeptime;
  1554.             DoPowerFail('O');
  1555.             quit = 1;
  1556.             break;
  1557.         default:
  1558.             Log(L_VB, "got unimplemented initrequest.");
  1559.             break;
  1560.     }
  1561.   }
  1562.  
  1563.   /* We come here if the pipe couldn't be opened. */
  1564.   if (pipe_fd < 0) pause();
  1565.  
  1566. }
  1567. #endif
  1568.  
  1569.  
  1570. /*
  1571.  * This function is used in the transition
  1572.  * sysinit (-> single user) boot -> multi-user.
  1573.  */
  1574. void BootTransitions()
  1575. {
  1576.   CHILD *ch;
  1577.   static int did_boot = 0;
  1578.   static int newlevel = 0;
  1579.   static int loglevel;
  1580.   static int oldlevel;
  1581.  
  1582.   /* Check if there is something to wait for! */
  1583.   for( ch = family; ch; ch = ch->next )
  1584.     if ((ch->flags & RUNNING) && ch->action != BOOT) break;
  1585.      
  1586.   if (ch == NULL) {
  1587.     /* No processes left in this level, proceed to next level. */
  1588.     loglevel = -1;
  1589.     oldlevel = 'N';
  1590.     switch(runlevel) {
  1591.         case '#': /* SYSINIT -> BOOT */
  1592. #if DEBUG
  1593.             Log(L_VB, "SYSINIT -> BOOT");
  1594. #endif
  1595.             /* Write a boot record. */
  1596.             wroteReboot = 0;
  1597.             WtmpOnly("reboot", "~~", 0, BOOT_TIME, "~");
  1598.  
  1599.               /* Get our run level */
  1600.               newlevel = dflLevel ? dflLevel : GetInitDefault();
  1601.             if (newlevel == 'S') {
  1602.                 runlevel = newlevel;
  1603.                 /* Not really 'S' but show anyway. */
  1604.                 setproctitle("init [S]");
  1605.             } else
  1606.                 runlevel = '*';
  1607.             break;
  1608.         case '*': /* BOOT -> NORMAL */
  1609. #if DEBUG
  1610.             Log(L_VB, "BOOT -> NORMAL");
  1611. #endif
  1612.             if (runlevel != newlevel)
  1613.                 loglevel = newlevel;
  1614.             runlevel = newlevel;
  1615.             did_boot = 1;
  1616.             break;
  1617.         case 'S': /* Ended SU mode */
  1618.         case 's':
  1619. #if DEBUG
  1620.             Log(L_VB, "END SU MODE");
  1621. #endif
  1622.             /* Save tty modes. */
  1623.             SetTerm(1);
  1624.             newlevel = GetInitDefault();
  1625.             if (!did_boot && newlevel != 'S')
  1626.                 runlevel = '*';
  1627.             else {
  1628.                 if (runlevel != newlevel)
  1629.                     loglevel = newlevel;
  1630.                 runlevel = newlevel;
  1631.                 oldlevel = 'S';
  1632.             }
  1633.             for(ch = family; ch; ch = ch->next)
  1634.                 if (strcmp(ch->rlevel, "S") == 0)
  1635.                 ch->flags &= ~(FAILING|WAITING|XECUTED);
  1636.             break;
  1637.         default:
  1638.             loglevel = -1;
  1639.             Log(L_VB, "no more processes left in this runlevel");
  1640. #if NEWINIT
  1641.             CheckInitFifo();
  1642. #else
  1643.             pause();
  1644. #endif
  1645.             break;
  1646.     }
  1647.     if (loglevel > 0) {
  1648.         Log(L_VB, "Entering runlevel: %c", runlevel);
  1649.         Wtmp("runlevel", "~~", runlevel + 256 * oldlevel, RUN_LVL, "~");
  1650.         thislevel = runlevel;
  1651.         prevlevel = oldlevel;
  1652.         setproctitle("init [%c]", runlevel);
  1653.     }
  1654.   }
  1655. }
  1656.  
  1657. /*
  1658.  * Init got hit by a signal. See which signal it is,
  1659.  * and act accordingly.
  1660.  */
  1661. void ProcessSignals()
  1662. {
  1663.   int pwrstat;
  1664.   int oldlevel;
  1665.   int fd;
  1666.   CHILD *ch;
  1667.   char c;
  1668.  
  1669.   if (sigismember(&got_signals, SIGPWR)) {
  1670. #if DEBUG
  1671.     Log(L_VB, "got SIGPWR");
  1672. #endif
  1673.     /* See _what_ kind of SIGPWR this is. */
  1674.     pwrstat = 0;
  1675.     if ((fd = open(PWRSTAT, O_RDONLY)) >= 0) {
  1676.         c = 0;
  1677.         read(fd, &c, 1);
  1678.         pwrstat = c;
  1679.         close(fd);
  1680.         unlink(PWRSTAT);
  1681.         DoPowerFail(pwrstat);
  1682.     }
  1683.     sigdelset(&got_signals, SIGPWR);
  1684.   }
  1685.  
  1686.   if (sigismember(&got_signals, SIGINT)) {
  1687. #if DEBUG
  1688.     Log(L_VB, "got SIGINT");
  1689. #endif
  1690.     /* Tell ctrlaltdel entry to start up */
  1691.     for(ch = family; ch; ch = ch->next)
  1692.         if (ch->action == CTRLALTDEL)
  1693.             ch->flags &= ~XECUTED;
  1694.     sigdelset(&got_signals, SIGINT);
  1695.   }
  1696.  
  1697.   if (sigismember(&got_signals, SIGWINCH)) {
  1698. #if DEBUG
  1699.     Log(L_VB, "got SIGWINCH");
  1700. #endif
  1701.     /* Tell kbrequest entry to start up */
  1702.     for(ch = family; ch; ch = ch->next)
  1703.         if (ch->action == KBREQUEST)
  1704.             ch->flags &= ~XECUTED;
  1705.     sigdelset(&got_signals, SIGWINCH);
  1706.   }
  1707.  
  1708.   if (sigismember(&got_signals, SIGALRM)) {
  1709. #if DEBUG
  1710.     Log(L_VB, "got SIGALRM");
  1711. #endif
  1712.     /* The timer went off: check it out */
  1713.     sigdelset(&got_signals, SIGALRM);
  1714.   }
  1715.  
  1716.   if (sigismember(&got_signals, SIGCHLD)) {
  1717. #if DEBUG
  1718.     Log(L_VB, "got SIGCHLD");
  1719. #endif
  1720.     /* First set flag to 0 */
  1721.     sigdelset(&got_signals, SIGCHLD);
  1722.  
  1723.     /* See which child this was */
  1724.     for(ch = family; ch; ch = ch->next)
  1725.         if (ch->flags & ZOMBIE) {
  1726. #if DEBUG
  1727.         Log(L_VB, "Child died, PID= %d", ch->pid);
  1728. #endif
  1729.         ch->flags &= ~(RUNNING|ZOMBIE|WAITING);
  1730.         if (ch->process[0] != '+')
  1731.             Wtmp("", ch->id, ch->pid, DEAD_PROCESS, NULL);
  1732.         }
  1733.  
  1734.   }
  1735.  
  1736.   if (sigismember(&got_signals, SIGHUP)) {
  1737. #if DEBUG
  1738.     Log(L_VB, "got SIGHUP");
  1739. #endif
  1740. #if CHANGE_WAIT
  1741.     /* Are we waiting for a child? */
  1742.     for(ch = family; ch; ch = ch->next)
  1743.         if (ch->flags & WAITING) break;
  1744.     if (ch == NULL)
  1745. #endif
  1746.     {
  1747.         /* We need to go into a new runlevel */
  1748.         oldlevel = runlevel;
  1749.         runlevel = ReadLevel(0);
  1750.         if (oldlevel != 'S' && runlevel == 'S') SetTerm(0);
  1751.         if (runlevel == '6' || runlevel == '0' || runlevel == '1') SetTerm(0);
  1752.         ReadItab();
  1753.         FailCancel();
  1754.         setproctitle("init [%c]", runlevel);
  1755.         sigdelset(&got_signals, SIGHUP);
  1756.     }
  1757.   }
  1758. }
  1759.  
  1760. /*
  1761.  * The main loop
  1762.  */ 
  1763. int InitMain()
  1764. {
  1765.   int f, st;
  1766.   CHILD *ch;
  1767.   struct sigaction sa;
  1768.   char *s;
  1769.  
  1770. #if INITDEBUG
  1771.   /*
  1772.    * Fork so we can debug the init process.
  1773.    */
  1774.   if ((f = fork()) > 0) {
  1775.     while(wait(&st) != f)
  1776.         ;
  1777.     write(1, "PRNT: init killed.\r\n", 20);
  1778.     while(1) pause();
  1779.   }
  1780. #endif
  1781.  
  1782. #ifdef ROOTFS
  1783.   /* Close all file descriptors. */
  1784.   close(0);
  1785.   close(1);
  1786.   close(2);
  1787.  
  1788.   /* Mount new root file system on /root */
  1789.   if (mount(ROOTFS, "/root", "ext2", 0, 0) < 0) {
  1790.     Log(L_VB, "mount(%s, /root): %s", ROOTFS, sys_errlist[errno]);
  1791.     while(1) pause();
  1792.   }
  1793.  
  1794.   /* Now do the chroot (needs kernel patch). */
  1795.   if (chroot("/root") < 0) {
  1796.     Log(L_VB, "chroot(/root): %s", sys_errlist[errno]);
  1797.     while(1) pause();
  1798.   }
  1799. #endif
  1800.  
  1801.   /* Tell the kernel to send us SIGINT when CTRL-ALT-DEL is pressed */
  1802.   reboot(0xfee1dead, 672274793, 0);
  1803.  
  1804.   /* Tell the kernel that we want to handle keyboard signals. */
  1805. #ifdef KDSIGACCEPT
  1806.   if ((f = open(VT_MASTER, O_RDWR | O_NOCTTY)) >= 0) {
  1807.       (void) ioctl(f, KDSIGACCEPT, SIGWINCH);
  1808.     close(f);
  1809.   } else
  1810.       (void) ioctl(0, KDSIGACCEPT, SIGWINCH);
  1811. #endif
  1812.  
  1813.   /* Set up signals */
  1814.   for(f = 1; f <= _NSIG; f++)
  1815.       signal(f, SIG_IGN);
  1816.  
  1817.   SETSIG(sa, SIGALRM,  signal_handler);
  1818.   SETSIG(sa, SIGHUP,   signal_handler);
  1819.   SETSIG(sa, SIGINT,   signal_handler);
  1820.   SETSIG(sa, SIGPWR,   signal_handler);
  1821.   SETSIG(sa, SIGWINCH, signal_handler);
  1822.   SETSIG(sa, SIGSTOP,  stop_handler);
  1823.   SETSIG(sa, SIGTSTP,  stop_handler);
  1824.   SETSIG(sa, SIGCONT,  cont_handler);
  1825.   SETSIG(sa, SIGSEGV,  segv_handler);
  1826.  
  1827.   /* Close whatever files are open, and reset the console. */
  1828.   close(0);
  1829.   close(1);
  1830.   close(2);
  1831.   if ((s = getenv("CONSOLE")) != NULL)
  1832.     console_dev = s;
  1833.   SetTerm(0);
  1834.   setsid();
  1835.  
  1836.   /* Set default PATH variable (for ksh) */
  1837.   if (getenv("PATH") == NULL) putenv(PATH_DFL);
  1838.  
  1839.   /* Initialize /var/run/utmp (only works if /var is on root and mounted rw) */
  1840.   (void) close(open(UTMP_FILE, O_WRONLY|O_CREAT|O_TRUNC, 0644));
  1841.  
  1842.   /* Say hello to the world */
  1843.   Log(L_CO, bootmsg);
  1844.  
  1845.   /* See if we have to start an emergency shell. */
  1846.   if (emerg_shell) {
  1847.     SETSIG(sa, SIGCHLD, SIG_DFL);
  1848.     if ((f = Spawn(&ch_emerg)) > 0) {
  1849.         while(wait(&st) != f)
  1850.             ;
  1851.     }
  1852.   }
  1853.   SETSIG(sa, SIGCHLD,  chld_handler);
  1854.  
  1855.   /* Start normal boot procedure. */
  1856.   runlevel = '#';
  1857.   ReadItab();
  1858.   StartEmIfNeeded();
  1859.  
  1860.   while(1) {
  1861.  
  1862.      /* See if we need to make the boot transitions. */
  1863.      BootTransitions();
  1864. #if DEBUG
  1865.      Log(L_VB, "InitMain: waiting..");
  1866. #endif
  1867.  
  1868.      /* Check if there are processes to be waited on. */
  1869.      for(ch = family; ch; ch = ch->next)
  1870.     if ((ch->flags & RUNNING) && ch->action != BOOT) break;
  1871. #if 0
  1872.      if (ch == NULL && got_signals == 0)
  1873.     Log(L_VB, "no more processes in this runlevel");
  1874. #endif
  1875.  
  1876. #if CHANGE_WAIT
  1877.      /* Wait until we get hit by some signal. */
  1878.      while (ch != NULL && got_signals == 0) {
  1879.     if (sigismember(&got_signals, SIGHUP)) {
  1880.         /* See if there are processes to be waited on. */
  1881.         for(ch = family; ch; ch = ch->next)
  1882.             if (ch->flags & WAITING) break;
  1883.     }
  1884. #  if NEWINIT
  1885.     if (ch != NULL) CheckInitFifo();
  1886. #  else
  1887.     if (ch != NULL) pause();
  1888. #  endif
  1889.      }
  1890. #else /* CHANGE_WAIT */
  1891. #  if NEWINIT
  1892.      if (ch != NULL && got_signals == 0) CheckInitFifo();
  1893. #  else
  1894.      if (ch != NULL && got_signals == 0) pause();
  1895. #  endif
  1896. #endif /* CHANGE_WAIT */
  1897.  
  1898.      /* Check the 'failing' flags */
  1899.      FailCheck();
  1900.  
  1901.      /* Process any signals. */
  1902.      ProcessSignals();
  1903.  
  1904.      /* See what we need to start up (again) */
  1905.      StartEmIfNeeded();
  1906.      sync();
  1907.   }
  1908.   /*NOTREACHED*/
  1909. }
  1910.  
  1911. /*
  1912.  * Tell the user about the syntax we expect.
  1913.  */
  1914. void Usage(char *s)
  1915. {
  1916.   fprintf(stderr, "Usage: %s 0123456SsQqAaBbCc\n", s);
  1917.   exit(1);
  1918. }
  1919.  
  1920. /*
  1921.  * Main entry for init and telinit.
  1922.  */
  1923. int main(int argc, char *argv[])
  1924. {
  1925. #if NEWINIT
  1926.   struct init_request request;
  1927. #endif
  1928.   char *p;
  1929.   FILE *fp;
  1930.   int f, fd;
  1931.  
  1932.   /* Get my own name */
  1933.   if ((p = strrchr(argv[0], '/')) != NULL)
  1934.       p++;
  1935.   else
  1936.       p = argv[0];
  1937.       
  1938.  
  1939.   /* See if I want to become "father of all processes" */
  1940. #ifndef TEST
  1941.   if (getpid() == INITPID || strcmp(p, "init.new") == 0 || strcmp(p, "sh") == 0) {
  1942. #else
  1943.                {
  1944. #endif
  1945.       /* Check command line arguments */
  1946.     maxproclen = strlen(argv[0]) + 1;
  1947.       for(f = 1; f < argc; f++) {
  1948.         if (!strcmp(argv[f], "single"))
  1949.             dflLevel = 'S';
  1950.         else if (!strcmp(argv[f], "-a") || !strcmp(argv[f], "auto"))
  1951.             putenv("AUTOBOOT=YES");
  1952.         else if (!strcmp(argv[f], "-b") || !strcmp(argv[f], "emergency"))
  1953.             emerg_shell = 1;
  1954.         else if (strchr("0123456789sS", argv[f][0])
  1955.             && strlen(argv[f]) == 1)
  1956.             dflLevel = argv[f][0];
  1957.         maxproclen += strlen(argv[f]) + 1;
  1958.     }
  1959.     maxproclen--;
  1960.  
  1961.     /* Start booting. */
  1962.     argv0 = argv[0];
  1963.     argv[1] = NULL;
  1964.     setproctitle("init boot");
  1965.     InitMain(dflLevel);
  1966.   }
  1967.  
  1968.   /* Nope, this is a change-run-level init */
  1969.   while((f = getopt(argc, argv, "t:")) != EOF) {
  1970.     switch(f) {
  1971.         case 't':
  1972.             sltime = atoi(optarg);
  1973.             break;
  1974.         default:
  1975.             Usage(p);
  1976.             break;
  1977.     }
  1978.   }
  1979.  
  1980.   if (geteuid() != 0) {
  1981.     fprintf(stderr, "init: must be superuser.\n");
  1982.     exit(1);
  1983.   }
  1984.  
  1985.   /* Check syntax. */
  1986.   if (argc - optind != 1 || strlen(argv[optind]) != 1) Usage(p);
  1987.   if (!strchr("0123456789SsQqAaBbCc", argv[optind][0])) Usage(p);
  1988.  
  1989.   umask(022);
  1990.  
  1991. #if NEWINIT
  1992.   /* Open the fifo and write a command. */
  1993.   memset(&request, 0, sizeof(request));
  1994.   request.magic     = INIT_MAGIC;
  1995.   request.cmd       = INIT_CMD_RUNLVL;
  1996.   request.runlevel  = argv[optind][0];
  1997.   request.sleeptime = sltime;
  1998.  
  1999.   /* Make sure we don't hang on opening /etc/init.fifo */
  2000.   signal(SIGALRM, signal_handler);
  2001.   alarm(3);
  2002.   if ((fd = open(INIT_FIFO, O_WRONLY)) >= 0 &&
  2003.         write(fd, &request, sizeof(request)) == sizeof(request)) {
  2004.     close(fd);
  2005.     alarm(0);
  2006.     return 0;
  2007.   }
  2008.   /* Fallthrough to the old method. */
  2009. #endif
  2010.   /* Now write the new runlevel. */
  2011.   if ((fp = fopen(INITLVL, "w")) == NULL) {
  2012.     fprintf(stderr, "%s: cannot create %s\n", p, INITLVL);
  2013.     exit(1);
  2014.   }
  2015.   fprintf(fp, "%s %d", argv[optind], sltime);
  2016.   fclose(fp);
  2017.  
  2018.   /* And tell init about the pending runlevel change. */
  2019.   if (kill(INITPID, SIGHUP) < 0) perror(p);
  2020.  
  2021.   exit(0);
  2022. }
  2023.